package milu.dbxml;

import java.util.Map;
import org.apache.log4j.Logger;

import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlQueryContext;
import com.sleepycat.dbxml.XmlQueryExpression;
import com.sleepycat.dbxml.XmlResults;
import com.sleepycat.dbxml.XmlTransaction;
import com.sleepycat.dbxml.XmlValue;

public class PreparedQuery implements Preparable {
	final static Logger log = Logger.getLogger(PreparedQuery.class);
	private final String query;
	private final DbXmlContext dbxml;
	private final Map<String, Object> variables;
	private XmlQueryExpression xqe;
	private XmlQueryContext xqc;

	public PreparedQuery(String query, DbXmlContext dbxml) {
		this(query, null, dbxml);
	}

	public PreparedQuery(String query, Map<String, Object> variables,
			DbXmlContext dbxml) {
		this.query = query;
		this.dbxml = dbxml;
		this.variables = variables;
	}

	@Override public void prepare() throws XmlException {
		XmlManager mgr = this.dbxml.getManager();
		XmlTransaction txn = mgr.createTransaction();
		xqc = this.dbxml.getQueryContext();
		log.info("prepare: " + this.query);
		if (null != this.variables) {
			for (Map.Entry<String, Object> entry : this.variables.entrySet()) {
				String key = entry.getKey();
				Object xo = entry.getValue();
				log.info("  param: " + key + " [" + xo.getClass().getName() + "]");
				if (xo instanceof XmlValue)
					xqc.setVariableValue(key, (XmlValue) xo);
				else
					xqc.setVariableValue(key, (XmlResults) xo);
			}
		}
		this.xqe = mgr.prepare(txn, this.query, xqc);
		txn.commit();
	}

	@Override public XmlResults execute(XmlTransaction txn) throws XmlException {
		return this.xqe.execute(txn, this.xqc); // XXX - gut so?
	}

	@Override public XmlResults execute(XmlTransaction txn, XmlQueryContext xqc)
			throws XmlException {
		return this.xqe.execute(txn, xqc);
	}

	@Override public void setVariable(String name, XmlValue value)
			throws XmlException {
		this.variables.put(name, value);
	}

	@Override public void setVariable(String name, XmlResults values)
			throws XmlException {
		this.variables.put(name, values);
	}

	@Override public XmlQueryExpression getQueryExpression() {
		return this.xqe;
	}
}
